//
// Created by 28365 on 2025/3/6.
//

#include "../include/utils/curl_modify/CURLCompatible.h"

size_t CURLCompatible::writeCallback(void *contents, size_t size, size_t nmemb, void *userp) {
    auto* cc = static_cast<CURLCompatible*>(userp);
    size_t total = size * nmemb;
    switch (cc->responseType) {
        case JSON:
            cc->result.append((char*)contents, total);
            return total;
        case FILE_DOWNLOAD:
            if (cc->outStream != nullptr && cc->getFileSize() != -1){
                cc->outStream->write(static_cast<char*>(contents), (ptrdiff_t)total).tellp();
                cc->addTransmitSize(total);
                cc->getOdUpdater().getStreamTransmit()->postTransmit(total,cc->getTransmitTotalSize(),cc->getFileSize(),*cc->res,cc->getOdUpdater());
                return total;
            }
            return 0;
        case UNKNOWN:
            return 0;
    }
    return 0;
}

size_t CURLCompatible::headerCallback(char *buffer, size_t size, size_t nitems, void *userp) {
    auto* cc = static_cast<CURLCompatible*>(userp);

    size_t totalSize = size * nitems;
    std::string header(buffer, totalSize);

    size_t colonPos = header.find(':');
    if (colonPos != std::string::npos) {
        std::string key = header.substr(0, colonPos);
        std::string value = header.substr(colonPos + 2);
        value.erase(value.find_last_not_of("\r\n") + 1);

        if (key == "Content-Type"){
            string type;

            size_t pos;
            if ((pos = value.find(';')) != string::npos){
                type = value.substr(0,pos);
            } else{
                type = value;
            }

            if (type == "application/json"){
                cc->setResponseType(JSON);
            } else if (type == "application/octet-stream"){
                cc->setResponseType(FILE_DOWNLOAD);
            } else{
                cc->setResponseType(UNKNOWN);
            }
        } else if (key == "Content-Length"){
            cc->setFileSize(stoll(value));

        }
    }

    //当当前为文件下载时发布回调事件
    if (!cc->isHandle && cc->getFileSize() != -1 && cc->getResponseType() == FILE_DOWNLOAD){
        cc->getOdUpdater().getLogger()->info("正在下载资源-->[资源ID:" + to_string(cc->res->getId()) + "]");
        cc->getOdUpdater().getUpdateHandler()->update({cc->res,cc->version,cc->getFileSize(),cc->getOutStream()});
        cc->isHandle = true;
    }

    return totalSize;
}

CURLCompatible::~CURLCompatible() {
    curl_easy_cleanup(curl);
}

void *CURLCompatible::getCurl() const {
    return curl;
}

void CURLCompatible::setResponseType(ResponseType _responseType) {
    CURLCompatible::responseType = _responseType;
}

void CURLCompatible::setResult(const string &_result) {
    CURLCompatible::result = _result;
}

size_t CURLCompatible::getFileSize() const {
    return CURLCompatible::fileSize;
}

void CURLCompatible::setFileSize(size_t _fileSize) {
    CURLCompatible::fileSize = _fileSize;
}

const ODUpdater &CURLCompatible::getOdUpdater() const {
    return *odUpdater;
}

const string &CURLCompatible::getResult() const {
    return result;
}

ResponseType CURLCompatible::getResponseType() const {
    return responseType;
}

ofstream *CURLCompatible::getOutStream() const {
    return outStream;
}

size_t CURLCompatible::getTransmitTotalSize() const {
    return transmitTotalSize;
}

void CURLCompatible::addTransmitSize(size_t size) {
    transmitTotalSize += size;
}

CURLCompatible::CURLCompatible(const ODUpdater *odUpdater):odUpdater(odUpdater){

}
